package com.yw.service.Impl;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.yw.ScriptInfo.domain.PythonScriptRequest;
import com.yw.ScriptInfo.domain.ScriptInfo;
import com.yw.ScriptInfo.vo.TaskScriptValueVO;
import com.yw.interfaceManageInfo.domain.InterfaceManageInfo;
import com.yw.interfaceManageInfo.dto.TestDTO;
import com.yw.interfaceManageInfo.vo.TaskInterfaceVO;
import com.yw.mapper.TaskMapper;
import com.yw.piliangDTO.StatusDTO;
import com.yw.result.R;
import com.yw.service.InterfaceService;
import com.yw.service.NodeService;
import com.yw.service.ScriptService;
import com.yw.service.TaskService;
import com.yw.task.domain.Node;
import com.yw.task.domain.Task;
import com.yw.task.dto.AddNodeDTO;
import com.yw.task.dto.AddTaskDTO;
import com.yw.task.dto.ExecuteTaskDTO;
import com.yw.task.dto.TaskQueryDTO;
import com.yw.task.vo.TaskQueryVO;
import com.yw.utils.BeanConverter;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.naming.ldap.PagedResultsControl;
import java.lang.reflect.Type;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class TaskMapperImpl extends ServiceImpl<TaskMapper, Task>
                            implements TaskService {

    @Resource
    private TaskMapper taskMapper;

    @Resource
    private NodeService nodeService;

    @Resource
    private InterfaceService interfaceService;

    @Resource
    private ObjectMapper objectMapper;

    @Resource
    private ScriptService scriptService;

    @Override
    public Boolean addTask(AddTaskDTO addTaskDTO) {
        LambdaQueryWrapper<Task> taskLambdaQueryWrapper = new LambdaQueryWrapper<>();
        taskLambdaQueryWrapper.eq(Task::getTaskName,addTaskDTO.getTaskName());
        Task one = this.getOne(taskLambdaQueryWrapper);
        if (ObjectUtils.isEmpty(one)) {
            Task task = new Task();
            task.setTaskCategory(addTaskDTO.getTaskCategory());
            task.setTaskName(addTaskDTO.getTaskName());
            task.setTaskDescription(addTaskDTO.getTaskDescription());
            task.setNode(JSONUtil.toJsonStr(addTaskDTO.getNode()));
            task.setCreateTime(LocalDateTime.now());
            task.setUpdateTime(LocalDateTime.now());
            task.setPublishStatus(0);
            return this.save(task);
        }else {
            return false;
        }
    }

    @Override
    public Page<TaskQueryVO> queryTask(TaskQueryDTO taskQueryDTO) {
        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(taskQueryDTO.getPublishStatus()!=null,Task::getPublishStatus,taskQueryDTO.getPublishStatus())
                .like(taskQueryDTO.getTaskName()!=null,Task::getTaskName,taskQueryDTO.getTaskName());
        Page<Task> taskPage = new Page<>(taskQueryDTO.getPageNumber(),taskQueryDTO.getPageSize());
        Page<Task> page = this.page(taskPage, wrapper);
        Page<TaskQueryVO> taskQueryVOPage = new Page<>();
        taskQueryVOPage.setRecords(BeanConverter.convertList(page.getRecords(),TaskQueryVO.class));
        taskQueryVOPage.setTotal(page.getTotal());
        taskQueryVOPage.setSize(page.getSize());
        taskQueryVOPage.setCurrent(page.getCurrent());

        return taskQueryVOPage;
    }

    //批量发布或停用
    @Override
    public Boolean batch(StatusDTO statusDTO) {
        return taskMapper.batch(statusDTO);
    }

    //    批量修改类型
    @Override
    public Boolean updateTypeBatch(List<Integer> ids, String type) {
        return taskMapper.updateTypeBatch(ids,type);
    }

    @Override
    public String executeTask(String taskName) {
        LambdaQueryWrapper<Node> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Node::getTaskName,taskName);
        List<Node> nodeList = nodeService.list(wrapper);
        // 分离 START 节点和其他节点
        List<Node> startNodes = new ArrayList<>();
        List<Node> otherNodes = new ArrayList<>();

        for (Node node : nodeList) {
            if ("START".equals(node.getNodeName())) {
                startNodes.add(node);
            } else {
                otherNodes.add(node);
            }
        }

        // 先处理 START 节点
        for (Node startNode : startNodes) {
            startNode.setLevel(1);
            nodeService.updateById(startNode);
        }

        // 再处理其他节点
        boolean hasNullLevel;
        do {
            hasNullLevel = false; // 假设没有null值

            // 设置每个节点的级别
            for (Node otherNode : otherNodes) {
                this.setLevel(otherNode);
                nodeService.updateById(otherNode);
            }

            // 检查是否有节点的级别为null
            for (Node otherNode : otherNodes) {
                if (otherNode.getLevel() == null) {
                    hasNullLevel = true; // 发现null值，设置标志为true
                    break; // 退出当前检查循环
                }
            }
        } while (hasNullLevel); // 如果有null值，重新执行循环

        this.executeNodeByLevel();
        return null;
    }

    //按照级别依次执行
    public void executeNodeByLevel(){
        int level = 1;
        boolean levelList;
        do {
            levelList = true;
            try {
                LambdaQueryWrapper<Node> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Node::getLevel, level);
                List<Node> list = nodeService.list(wrapper);
                if (list.isEmpty()){
                    levelList = false;
                }else {
                    level+=1;
                }
                for (Node node : list) {
                    switch (node.getNodeType()) {
                        case "API":
                            InterfaceManageInfo oneInterface = interfaceService.getById(node.getInterfaceId());
                            TestDTO testDTO = new TestDTO();
                            testDTO.setAgreement(oneInterface.getRequestMethod());
                            testDTO.setRequestURL(oneInterface.getAgreement().toLowerCase() + "://" + oneInterface.getIp() + oneInterface.getPath());
                            // 创建ObjectMapper实例
                            try {
                                // 将JSON字符串解析为JsonNode
                                JsonNode jsonNode = objectMapper.readTree(node.getNodeInValues());

                                // 创建一个Map来存储需要的字段
                                Map<String, Object> resultMap = new HashMap<>();

                                // 从JsonNode中获取valueName和testValue并存入Map
                                for (JsonNode element : jsonNode) {
                                    // 在每个数组元素（对象）中检查是否有 "valueName" 键
                                    if (element.has("valueName")) {
                                        resultMap.put("valueName", element.get("valueName").asText());
                                    }
                                    if (element.has("testValue")) {
                                        resultMap.put("testValue", element.get("testValue").asText());
                                    }
                                }
                                testDTO.setMap(resultMap);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            R test = interfaceService.test(testDTO);
                            System.out.println(test);
                            break;
                        case "PY":
                            ScriptInfo scriptOne = scriptService.getById(node.getPyId());//得到脚本单条数据
                            PythonScriptRequest pythonScriptRequest = new PythonScriptRequest();
                            pythonScriptRequest.setId(node.getPyId());
                            try {
                                // 将JSON字符串解析为JsonNode
                                JsonNode jsonNode = objectMapper.readTree(node.getNodeInValues());

                                // 创建一个Map来存储需要的字段
                                Map<String, String> resultMap = new HashMap<>();

                                // 从JsonNode中获取valueName和testValue并存入Map
                                for (JsonNode element : jsonNode) {
                                    // 在每个数组元素（对象）中检查是否有 "valueName" 键
                                    if (element.has("valueName")) {
                                        resultMap.put("valueName", element.get("valueName").asText());
                                    }
                                    if (element.has("testValue")) {
                                        resultMap.put("testValue", element.get("testValue").asText());
                                    }
                                }
                                pythonScriptRequest.setParams(resultMap);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            R r = scriptService.executePythonScript(pythonScriptRequest);
                            System.out.println(r);
                            break;
                        case "OUT":
                            break;
                        case "CLEAN":
                            break;
                        case "MAPPING":
                            break;
                    }
                    //循环结束，执行完了start下的所有节点逻辑，现在依次执行子节点，现在的问题是如何执行start子节点的子节点
                }
            }catch(Exception e){
                throw new RuntimeException(e);
            }
        }while (levelList);
    }

    //设置子节点级别为本身+1
    public void setLevel(Node node){
        try {
            List<Integer> upstreamIds = objectMapper.readValue(node.getUpstreamIds(), new TypeReference<List<Integer>>() {});
            for (Integer upstreamId : upstreamIds) {
                Node one = nodeService.getById(upstreamId);
                if (node.getLevel() != null) {
                    one.setLevel(node.getLevel() + 1);
                    nodeService.updateById(one);
                }
            }
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }


}
